pub type Label String derive(Show)

pub typealias Name = @types.Name

pub typealias Type = @types.Type

pub enum Expr {
  Unit
  Int(Int)
  Double(Double)
  Neg(Name)
  Add(Name, Name)
  Sub(Name, Name)
  Mul(Name, Name)
  Div(Name, Name)
  FNeg(Name)
  FAdd(Name, Name)
  FSub(Name, Name)
  FMul(Name, Name)
  FDiv(Name, Name)
  IfEq(Name, Name, Expr, Expr)
  IfLe(Name, Name, Expr, Expr)
  Let((Name, LowType), Expr, Expr)
  Var(Name)
  MakeClosure((Name, LowType), Closure, Expr)
  CallClosure(Name, Array[Name])
  CallDirect(Label, Array[Name])
  MakeTuple(Array[Name])
  LetTuple(Array[(Name, LowType)], Name, Expr)
  ArrayGet(Name, Name)
  ArrayPut(Name, Name, Name)
  ExternalArray(Label)
} derive(Show)

pub struct Closure {
  name : Label
  actual_free_vars : Array[Name]
} derive(Show)

pub struct FuncDef {
  name : Label
  old_name : Name
  ty : LowType
  args : Array[(Name, LowType)]
  formal_free_vars : Array[(Name, LowType)]
  body : Expr
} derive(Show)

pub struct Program {
  fundefs : Array[FuncDef]
  body : Expr
} derive(Show)
